package org.infodavid.common.persistence;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import junit.framework.Assert;

import org.junit.Test;

import org.infodavid.common.dto.IUserGroupListItem;
import org.infodavid.common.dto.IUserListItem;
import org.infodavid.common.dto.IUserGroupListItem.EUserRole;
import org.infodavid.common.impl.model.criteria.UserGroupCriteriaImpl;
import org.infodavid.common.model.GroupTest;
import org.infodavid.common.model.IUser;
import org.infodavid.common.model.IUserGroup;
import org.infodavid.common.model.UserTest;
import org.infodavid.common.model.criteria.IUserGroupCriteria;

/**
 * The Class GroupDataServiceTest.
 */
@SuppressWarnings({
	"null"
})
public class GroupDataServiceTest extends
    AbstractDataServiceTest<IUserGroupListItem,IUserGroup,Long> {

	/** The user test. */
	private final UserTest userTest = new UserTest(this);

	/**
	 * The Constructor.
	 */
	public GroupDataServiceTest() {
		super(new GroupTest(), UserGroupDataService.getInstance());
	}

	/*
	 * See super class or interface. (non-Javadoc)
	 * @see
	 * org.infodavid.common.persistence.AbstractDataServiceTest#modify(org.infodavid.common.model.IDataObject
	 * )
	 */
	@Override
	public void modify(final IUserGroup item) {
		item.setComment("ModifiedComment");
		item.setLocked(!item.isLocked());
	}

	/**
	 * Test get instance.
	 */
	@Test
	public final void testGetInstance() {
		Assert.assertEquals("Not a singleton", UserGroupDataService.getInstance(),
		    UserGroupDataService.getInstance());
	}

	/**
	 * Test find.
	 * @throws Exception the exception
	 */
	@Test
	public void testFindByCriteria() throws Exception {
		final List<IUserGroupListItem> results = new ArrayList<IUserGroupListItem>();
		final IUserGroupCriteria criteria = new UserGroupCriteriaImpl();
		final long count = ((UserGroupDataService)getService()).find(getSession(), results, criteria);

		//System.out.println(results);

		Assert.assertNotNull("Result is null", results);
		Assert.assertEquals("Not all data has been found", ITEMS_TO_INSERT, results.size());
		Assert.assertEquals("Not all data has been found", ITEMS_TO_INSERT, count);
	}

	/**
	 * Test find.
	 * @throws Exception the exception
	 */
	@Test
	public void testFindByCriteriaUsingAllCriterions() throws Exception {
		final Collection<IUserGroup> inserted = getTestData();
		final IUserGroup group = inserted.iterator().next();
		final List<IUserGroupListItem> results = new ArrayList<IUserGroupListItem>();
		final IUserGroupCriteria criteria = new UserGroupCriteriaImpl();

		criteria.setNamePattern(group.getName());
		criteria.setRole(group.getRole());

		final long count = ((UserGroupDataService)getService()).find(getSession(), results, criteria);

		//System.out.println(results);

		Assert.assertNotNull("Result is null", results);
		Assert.assertEquals("Not all data has been found", 1, results.size());
		Assert.assertEquals("Not all data has been found", 1, count);
		Assert.assertEquals("Wrong data found", group, results.get(0));
	}

	/**
	 * Test find.
	 * @throws Exception the exception
	 */
	@Test
	public void testFindByCriteriaUsingNameNoDataFound() throws Exception {
		final List<IUserGroupListItem> results = new ArrayList<IUserGroupListItem>();
		final IUserGroupCriteria criteria = new UserGroupCriteriaImpl();

		criteria.setNamePattern("NoData");

		final long count = ((UserGroupDataService)getService()).find(getSession(), results, criteria);

		//System.out.println(results);

		Assert.assertNotNull("Result is null", results);
		Assert.assertEquals("Not all data has been found", 0, results.size());
		Assert.assertEquals("Not all data has been found", 0, count);
	}

	/**
	 * Test find.
	 * @throws Exception the exception
	 */
	@Test
	public void testFindByCriteriaUsingRole() throws Exception {
		final Collection<IUserGroup> inserted = getTestData();
		final List<IUserGroupListItem> results = new ArrayList<IUserGroupListItem>();
		final IUserGroupCriteria criteria = new UserGroupCriteriaImpl();
		final IUserGroup group = inserted.iterator().next();
		int expectedCount = 0;

		criteria.setRole(group.getRole());

		for (final IUserGroup item : inserted) {
			if (item.getRole().equals(group.getRole())) {
				expectedCount++;
			}
		}

		final long count = ((UserGroupDataService)getService()).find(getSession(), results, criteria);

		//System.out.println(results);

		Assert.assertNotNull("Result is null", results);
		Assert.assertEquals("Not all data has been found", expectedCount, results.size());
		Assert.assertEquals("Not all data has been found", expectedCount, count);
	}

	/**
	 * Test find.
	 * @throws Exception the exception
	 */
	@Test
	public void testFindByCriteriaUsingNameEqual() throws Exception {
		final Collection<IUserGroup> inserted = getTestData();
		final List<IUserGroupListItem> results = new ArrayList<IUserGroupListItem>();
		final IUserGroupCriteria criteria = new UserGroupCriteriaImpl();

		criteria.setNamePattern(inserted.iterator().next().getName());

		final long count = ((UserGroupDataService)getService()).find(getSession(), results, criteria);

		//System.out.println(results);

		Assert.assertNotNull("Result is null", results);
		Assert.assertEquals("Not all data has been found", 1, results.size());
		Assert.assertEquals("Not all data has been found", 1, count);
	}

	/**
	 * Test find.
	 * @throws Exception the exception
	 */
	@Test
	public void testFindByCriteriaUsingNameLike() throws Exception {
		final List<IUserGroupListItem> results = new ArrayList<IUserGroupListItem>();
		final IUserGroupCriteria criteria = new UserGroupCriteriaImpl();

		criteria.setNamePattern("item%");

		final long count = ((UserGroupDataService)getService()).find(getSession(), results, criteria);

		//System.out.println(results);

		Assert.assertNotNull("Result is null", results);
		Assert.assertEquals("Not all data has been found", ITEMS_TO_INSERT, results.size());
		Assert.assertEquals("Not all data has been found", ITEMS_TO_INSERT, count);
	}

	/**
	 * Test find.
	 * @throws Exception the exception
	 */
	@Test
	public void testFindByCriteriaUsingNullCollection() throws Exception {
		final IUserGroupCriteria criteria = new UserGroupCriteriaImpl();
		Exception exception = null;

		try {
			((UserGroupDataService)getService()).find(getSession(), null, criteria);
		}
		catch (final Exception e) {
			exception = e;
			e.printStackTrace();
		}

		Assert.assertNotNull("No exception thrown", exception);
		Assert.assertEquals("Wrong exception thrown", IllegalArgumentException.class,
		    exception.getClass());
	}

	/**
	 * Test find.
	 * @throws Exception the exception
	 */
	@Test
	public void testFindByCriteriaUsingNullCriteria() throws Exception {
		final List<IUserGroupListItem> results = new ArrayList<IUserGroupListItem>();
		final long count =
		    ((UserGroupDataService)getService()).find(getSession(), results, (IUserGroupCriteria)null);

		//System.out.println(results);

		Assert.assertNotNull("Result is null", results);
		Assert.assertEquals("Not all data has been found", ITEMS_TO_INSERT, results.size());
		Assert.assertEquals("Not all data has been found", ITEMS_TO_INSERT, count);
	}

	/**
	 * Test find.
	 * @throws Exception the exception
	 */
	@Test
	public void testFindByCriteriaUsingPage() throws Exception {
		final List<IUserGroupListItem> results = new ArrayList<IUserGroupListItem>();
		final IUserGroupCriteria criteria = new UserGroupCriteriaImpl();

		criteria.setPageStart(Long.valueOf(0));
		criteria.setPageSize(Integer.valueOf(5));

		final long count = ((UserGroupDataService)getService()).find(getSession(), results, criteria);

		//System.out.println(results);

		Assert.assertNotNull("Result is null", results);
		Assert.assertEquals("Not all data has been found", criteria.getPageSize().intValue(),
		    results.size());
		Assert.assertEquals("Not all data has been found", ITEMS_TO_INSERT, count);
	}

	/**
	 * Test find.
	 * @throws Exception the exception
	 */
	@Test
	public void testFindByName() throws Exception {
		final Collection<IUserGroup> inserted = getTestData();
		final IUserGroup result =
		    ((UserGroupDataService)getService()).findByName(getSession(), inserted.iterator().next()
		        .getName());

		Assert.assertNotNull("Result is null", result);
		Assert.assertEquals("Wrong data found", inserted.iterator().next().getName(), result.getName());
		Assert.assertEquals("Wrong data found", inserted.iterator().next().getKey(), result.getKey());
	}

	/**
	 * Test find.
	 * @throws Exception the exception
	 */
	@Test
	public void testFindByNameUsingNull() throws Exception {
		Exception exception = null;

		try {
			((UserGroupDataService)getService()).findByName(getSession(), null);
		}
		catch (final Exception e) {
			exception = e;
			e.printStackTrace();
		}

		Assert.assertNull("Exception thrown", exception);
	}

	/**
	 * Test find.
	 * @throws Exception the exception
	 */
	@Test
	public void testFindByGuest() throws Exception {
		final Collection<IUserGroup> inserted = getTestData();
		final List<IUserGroup> results = new ArrayList<IUserGroup>();
		final long count =
		    ((UserGroupDataService)getService()).findByGuest(getSession(), true, results, null);

		//System.out.println(results);

		int expectedCount = 0;

		for (final IUserGroup item : inserted) {
			expectedCount += item.isGuest() ? 1 : 0;
		}

		Assert.assertNotNull("Result is null", results);
		Assert.assertEquals("Not all data has been found", expectedCount, results.size());
		Assert.assertEquals("Not all data has been found", expectedCount, count);

		for (final IUserGroup item : results) {
			Assert.assertTrue("Wrong datan found", item.isGuest());
		}
	}

	/**
	 * Test find.
	 * @throws Exception the exception
	 */
	@Test
	public void testFindByGuestUsingNullCollection() throws Exception {
		Exception exception = null;

		try {
			((UserGroupDataService)getService()).findByGuest(getSession(), true, null, null);
		}
		catch (final Exception e) {
			exception = e;
			e.printStackTrace();
		}

		Assert.assertNotNull("No exception thrown", exception);
		Assert.assertEquals("Wrong exception thrown", IllegalArgumentException.class,
		    exception.getClass());
	}

	/**
	 * Test add member.
	 * @throws Exception the exception
	 */
	@Test
	public void testAddMember() throws Exception {
		final Collection<IUserGroup> inserted = getTestData();
		final PersistenceSession session = getSession();
		final IUserGroup group = inserted.iterator().next();
		final IUser user = userTest.populate(1).iterator().next();

		((UserGroupDataService)getService()).addMembers(getSession(), group.getKey().longValue(), user
		    .getKey().longValue());

		final List<IUserListItem> results = new ArrayList<IUserListItem>();
		boolean found = false;

		UserDataService.getInstance().findByGroup(session, group.getKey(), results, null);

		Assert.assertFalse("Member has not been added", results.isEmpty());

		for (final IUserListItem item : results) {
			if (item.getKey().equals(user.getKey())) {
				found = true;

				break;
			}
		}

		Assert.assertTrue("Member has not been added", found);
	}

	/**
	 * Test remove member.
	 * @throws Exception the exception
	 */
	@Test
	public void testRemoveMember() throws Exception {
		final Collection<IUserGroup> inserted = getTestData();
		final PersistenceSession session = getSession();
		final IUserGroup group = inserted.iterator().next();
		final IUser user = userTest.populate(1).iterator().next();

		((UserGroupDataService)getService()).addMembers(getSession(), group.getKey().longValue(), user
		    .getKey().longValue());

		final List<IUserListItem> results = new ArrayList<IUserListItem>();
		boolean found = false;

		UserDataService.getInstance().findByGroup(session, group.getKey(), results, null);

		Assert.assertFalse("Member has not been added", results.isEmpty());

		for (final IUserListItem item : results) {
			if (item.getKey().equals(user.getKey())) {
				found = true;

				break;
			}
		}

		Assert.assertTrue("Member has not been added", found);

		((UserGroupDataService)getService()).removeMembers(getSession(), group.getKey().longValue(),
		    user.getKey().longValue());
		results.clear();
		UserDataService.getInstance().findByGroup(session, group.getKey(), results, null);
		found = false;

		for (final IUserListItem item : results) {
			if (item.getKey().equals(user.getKey())) {
				found = true;

				break;
			}
		}

		Assert.assertFalse("Member has not been removed", found);
	}

	/**
	 * Test find.
	 * @throws Exception the exception
	 */
	@Test
	public void testFindByRole() throws Exception {
		final Collection<IUserGroup> inserted = getTestData();
		final List<IUserGroup> results = new ArrayList<IUserGroup>();
		final EUserRole role = inserted.iterator().next().getRole();
		final long count =
		    ((UserGroupDataService)getService()).findByRole(getSession(), role, results, null);

		//System.out.println(results);

		int expectedCount = 0;

		for (final IUserGroup item : inserted) {
			expectedCount += item.getRole() == role ? 1 : 0;
		}

		Assert.assertNotNull("Result is null", results);
		Assert.assertEquals("Not all data has been found", expectedCount, results.size());
		Assert.assertEquals("Not all data has been found", expectedCount, count);

		for (final IUserGroupListItem item : results) {
			Assert.assertEquals("Wrong datan found", role, item.getRole());
		}
	}

	/**
	 * Test find.
	 * @throws Exception the exception
	 */
	@Test
	public void testFindByRoleUsingNull() throws Exception {
		final List<IUserGroup> results = new ArrayList<IUserGroup>();
		Exception exception = null;

		try {
			((UserGroupDataService)getService()).findByRole(getSession(), null, results, null);
		}
		catch (final Exception e) {
			exception = e;
			e.printStackTrace();
		}

		Assert.assertNull("No exception thrown", exception);
	}

	/**
	 * Test find.
	 * @throws Exception the exception
	 */
	@Test
	public void testFindByRoleUsingNullCollection() throws Exception {
		final Collection<IUserGroup> inserted = getTestData();
		Exception exception = null;

		try {
			((UserGroupDataService)getService()).findByRole(getSession(), inserted.iterator().next()
			    .getRole(), null, null);
		}
		catch (final Exception e) {
			exception = e;
			e.printStackTrace();
		}

		Assert.assertNotNull("No exception thrown", exception);
		Assert.assertEquals("Wrong exception thrown", IllegalArgumentException.class,
		    exception.getClass());
	}
}
